Repository navigation
feat(mcp-server): Ship @sentry/mcp-server as a slim bundle that shares CLI auth - #1731
sentry-junior[bot] wants to merge 40 commits into
Conversation
Move the stdio MCP host into the CLI so `sentry mcp` is the only local server. The stdio transport moves to mcp-core; flag/env parsing, usage, and server startup move to packages/cli/src/lib/mcp/. The standalone device-code auth and token cache are deleted in favor of CLI auth. `sentry mcp` keeps every standalone flag and env var, and accepts `--access-token` / `SENTRY_ACCESS_TOKEN` as a static, never-refreshed token that still goes through host scoping. Lock the dependency direction (cli -> mcp-core -> toolkit-core) with an oxlint import ban and a workspace manifest cycle check, move the MCP registry entry to the `sentry` package, and reduce @sentry/mcp-server to a deprecation shim for one last release. Co-Authored-By: BYK <burak.kaya@sentry.io>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The doc example checker reads backticked sentry commands in the generated configuration page and does not know about `sentry mcp` passthrough flags. Co-Authored-By: BYK <burak.kaya@sentry.io>
The retired package fixed the SDK environment to "stdio" at build time. Co-Authored-By: BYK <burak.kaya@sentry.io>
…nippet Tool handlers read mcp-core's own copy of the server context, so updating the host's context after a refresh had no effect. onUpstreamUnauthorized can now return the new token, and mcp-core stores it where handlers read it. The fx profile snippet also ran plain `npx sentry@latest`. Co-Authored-By: BYK <burak.kaya@sentry.io>
…-package Co-Authored-By: BYK <burak.kaya@sentry.io>
Oxlint replaces a rule's options per override, so the toolkit-core browser override silently dropped the earlier CLI ban. Carry the ban there and test the last matching override for each package. Co-Authored-By: BYK <burak.kaya@sentry.io>
…-package # Conflicts: # pnpm-lock.yaml Co-Authored-By: BYK <burak.kaya@sentry.io>
Bundle the CLI's stdio MCP server into one dependency-free file instead of forwarding to the sentry CLI. The package keeps its flags, env vars, and self-hosted support, and adds a plain-text `sentry-mcp auth login`. The bundle script keeps CLI-only code out (commands, markdown renderer, agent skills, completions, terminal images, Ink UI, debug files) and drops the SQLite WASM fallback, so the package requires Node.js 22.15+. It fails the build if a CLI-only module reaches the output or the file exceeds 4.5 MB. Co-Authored-By: BYK <burak.kaya@sentry.io>
These invocations finish like any other drained command but skipped the force-exit backstop and dispatcher close that runCli applies, so leftover handles could keep the process alive on macOS. startMcpServer now reports whether a server is running, and runMcpServer and the standalone auth entry release resources whenever the invocation is finite.
…-package Co-Authored-By: BYK <burak.kaya@sentry.io>
…/retire-mcp-server-package Co-Authored-By: BYK <burak.kaya@sentry.io>
…into ref/retire-mcp-server-package Co-Authored-By: BYK <burak.kaya@sentry.io>
…ef/retire-mcp-server-package Co-Authored-By: BYK <burak.kaya@sentry.io>
`sentry mcp` and `@sentry/mcp-server` now build the server with `sdkVersion: "v2"` and connect it through `@modelcontextprotocol/server`'s stdio transport, the SDK the Cloudflare worker already runs. Both serve the same 14 tools as before. v2's transport closes when the client closes stdin, and `startStdio()` now returns a `closed` promise for that, so a host can tear down only after the session ends. `buildServer()` still defaults to v1 for other callers. Co-Authored-By: BYK <burak.kaya@sentry.io>
`@sentry/mcp-server` no longer has its own entry logic. `mcp-server.ts` runs `cli.ts`'s runner with `mcp-server-app.ts`, a route map of the CLI's real `mcp` (the default command), `auth`, and `help`. So `sentry-mcp auth status|list|switch|logout` work, and flags and help for `sentry mcp` and `sentry-mcp` come from one Stricli definition. - The runner takes a `CliEntry` that loads the application, and starts `mcp` without the CLI's telemetry, recovery middleware, and update check. The command resolves when the client closes stdin, and only then does the runner release the network. - `lib/app-identity.ts` replaces `login-command.ts`: hints and help examples name `sentry-mcp`, or `npx -y @sentry/mcp-server` under npx. - `--flag=` and values with line breaks still parse, as they did with the old parser (`splitInlineFlagValues`). - A bare `--version` answers before the application loads (86 MB, 140 ms). The server stack loads only when `mcp` serves. - The bundle adds #1763's Zod English-locale plugin, compiles out syntax highlighting and the Ink picker, and stubs MCP SDK v1's `McpServer` and `zod/v3`. It is 3,689,911 bytes; the budget is 3.75 MiB. Co-Authored-By: BYK <burak.kaya@sentry.io>
Co-Authored-By: BYK <burak.kaya@sentry.io>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 7a2f0a2. Configure here.
The old package treated `-v` as `--version`. In the unified build the CLI's global flags own `-v` as `--verbose`, so `sentry-mcp -v` started the server instead. Answer a lone `-v` from the same fast path as `--version`. Co-Authored-By: BYK <burak.kaya@sentry.io>
`commands/mcp.ts` imported `@sentry/mcp-core/skills` for its help text, so loading any command needed mcp-core's build output. Docs generation (`sentry-cli-docs`, cli-build's docs job) and a fresh `pnpm run cli` load every command without building mcp-core, and failed. Copy the skill names into the command and guard the copy with a test. Co-Authored-By: BYK <burak.kaya@sentry.io>
| try { | ||
| console.error(label, error); | ||
| } catch { | ||
| // stderr may already be closed | ||
| } |
There was a problem hiding this comment.
Fatal MCP errors exit 0 when stderr EPIPE fires during console.error
exitAfterError always intends process.exit(1), but its console.error hits the entrypoint stderr EPIPE handler (installStreamErrorHandlers), which calls process.exit(0) first—so crashes after the client closes pipes report success.
Evidence
bin.tsandmcp-server.tsboth callinstallStreamErrorHandlers(), which doesprocess.exit(0)on stderrEPIPE(seelib/stream-errors.ts).exitAfterErrorwrites withconsole.error(label, error)even when it expects pipes to be closed (comment references stdio server spins forever at 100%+ CPU when the client dies: uncaughtException handler re-throws EPIPE on a broken stderr #1274), and only then schedulesprocess.exit(1).- With an error listener on stderr, a write EPIPE is emitted to that handler rather than thrown into the
try/catch, soprocess.exit(0)runs before the fatalprocess.exit(1)paths. installProcessHandlerstests mockconsole.errorand never install the stream handlers, so they do not catch this exit-code inversion.
Also found at 1 additional location
packages/cli/src/lib/stream-errors.ts:15-16
Identified by Warden · code-review · BU4-DK5
| !(hasSentryTarget(flags) || (staticToken && parseSntrysClaim(staticToken))) | ||
| ) { | ||
| const { assertRcUrlTrusted } = await import("./sentryclirc.js"); | ||
| await assertRcUrlTrusted(process.cwd()); |
There was a problem hiding this comment.
MCP startup fails when its working directory has been deleted
When sentry mcp starts from a deleted worktree, this call evaluates process.cwd() and throws ENOENT before the rc trust check can no-op, so the server does not start. Use the resolved command-context cwd or the same PWD fallback as buildContext.
Evidence
buildContextusesresolveCwd, which falls back to absolutePWDwhenprocess.cwd()throws;runMcpServerbuilds that context before dispatching the MCP command.mcpCommandcallsserveMcp(flags)without passing the context cwd, andserveMcpcallsprocess.cwd()again when no explicit target or claimed org token bypasses the trust check.- The
process.cwd()argument is evaluated beforeassertRcUrlTrustedruns, so even the no-rc-URL no-op cannot prevent the error;runMcpServercatches it and exits without starting the server.
Identified by Warden · code-review · 5YZ-RXX
Every caller (sentry mcp, the Cloudflare worker, the eval mock server) already asked for SDK v2, so buildServer() now always builds a v2 McpServer and the sdkVersion option, its overloads, and the v1 branch are gone. mcp-core's remaining SDK v1 imports were types; they now come from @modelcontextprotocol/server, and the unused RegisteredToolHandlerExtra type is deleted. @modelcontextprotocol/sdk moves to mcp-core's devDependencies (tests drive the server with its in-memory client) and leaves mcp-server-evals, which never imported it. The @sentry/mcp-server bundle no longer needs its SDK v1 stub, and now fails if any @modelcontextprotocol/sdk module reaches it. The CLI bundle drops SDK v1's server, zod-compat, its ajv, and zod-to-json-schema: dist/index.cjs goes from 7,426,174 to 7,203,971 bytes. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
Everything we bundle builds Zod 4 schemas, but two dependencies still import zod/v3 for Zod 3 inputs: @ai-sdk/provider-utils (zod3Schema and its copy of zod-to-json-schema) and @mastra/schema-compat (its Zod 3 converter, plus an instanceof z3.ZodType check in isZodV3). sentry init only uses Mastra's workflow client, which converts no schemas. zodV3StubPlugin replaces zod/v3 with a stub shared by script/bundle.ts, script/build.ts, and the @sentry/mcp-server bundle. ZodType stays a class so the instanceof check is false, and ZodFirstPartyTypeKind throws a clear error if a Zod 3 schema ever reaches a converter. The test bundles the real Mastra client and provider-utils, runs a workflow create/start, converts Zod 4 and JSON schemas, and checks no zod/v3 module is included. CLI dist/index.cjs: 7,203,971 -> 7,142,739 bytes. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
`sentry mcp` and `@sentry/mcp-server` take a token in --access-token, but setFlagContext only redacted `token`, so the value became a `flag.access-token` tag. Add it to the flag and argv redaction lists. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
--access-token and SENTRY_ACCESS_TOKEN used to bypass the CLI's credential resolution with a static-token path of their own. They now run the server as if SENTRY_AUTH_TOKEN=<token> and SENTRY_FORCE_ENV_TOKEN=1 were set: the token goes into an env copy (withEnv), so it takes the CLI's env-token path, wins over a stored login, and replaces any SENTRY_AUTH_TOKEN/SENTRY_TOKEN already set, since the flag is the explicit choice. The flag wins over SENTRY_ACCESS_TOKEN. The copy's URL is pinned to the --host/--url target, as the old static token was; an org token's claim must still match it. The .sentryclirc check runs against the invocation's own credentials first. Either one prints a single deprecation warning on stderr (stdout is the MCP transport) that never includes the token. resolveStaticMcpAccessToken and the accessToken config fields are gone. The help text, stdio-auth, READMEs, server.json, and the testing docs now lead with SENTRY_AUTH_TOKEN (plus SENTRY_FORCE_ENV_TOKEN=1, and SENTRY_HOST/SENTRY_URL for self-hosted). The test client and the eval scorer launch the server with those env vars instead of --access-token. Co-Authored-By: BYK <126780+BYK@users.noreply.github.com>
| const server = new McpServer({ | ||
| name: MCP_SERVER_NAME, | ||
| version: LIB_VERSION, | ||
| }; | ||
|
|
||
| if (sdkVersion === "v2") { | ||
| const server = new ModernMcpServer(serverInfo); | ||
| const registrations = configureServer({ | ||
| server, | ||
| context: contextWithModes, | ||
| experimentalMode, | ||
| tools: customTools, | ||
| }); | ||
| for (const { name, config, handler } of registrations) { | ||
| server.registerTool(name, config, handler); | ||
| } | ||
| if (registrations.length > 0) { | ||
| server.server.registerCapabilities({ tools: { listChanged: false } }); | ||
| } | ||
| return wrapMcpServerWithSentry(server); | ||
| } | ||
|
|
||
| const server = new LegacyMcpServer(serverInfo); | ||
| }); |
There was a problem hiding this comment.
High severity vulnerability may affect your project—review required:
Line 143 lists a dependency (@modelcontextprotocol/server) with a known High severity vulnerability.
ℹ️ Why this matters
Affected versions of @modelcontextprotocol/sdk and @modelcontextprotocol/server are vulnerable to Allocation of Resources Without Limits or Throttling. McpServer places no limit on how many array elements and object keys it validates in tool-call arguments. A single unauthenticated HTTP request within the default 4 MiB body limit can exhaust the Node.js heap during validation and crash the server process (denial of service). After upgrading, also set the opt-in maxToolInputElements McpServer option and lower maxRequestBodySize.
References: GHSA
To resolve this comment:
Check if you expose the McpServer over an HTTP transport (Streamable HTTP, SSE, or createMcpHandler) rather than stdio only and it registers tools that accept input, especially arrays or records.
- If you're affected, upgrade this dependency to at least version 2.3.0 at pnpm-lock.yaml.
- If you're not affected, comment
/fp we don't use this [condition]
💬 Ignore this finding
To ignore this, reply with:
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
You can view more details on this finding in the Semgrep AppSec Platform here.

@sentry/mcp-serverstays the recommended stdio install. Its server code moves into the CLI so it shares the CLI's auth, and the package becomes a slim, dependency-free bundle of that code (see the@sentry/mcp-serversection below). The CLI exposes the same server assentry mcp. This also locks in a one-way package graph, so MCP tools can later be built on the CLI's portable operations without a cycle.What moved where
packages/mcp-server/src/transports/stdio.ts→packages/mcp-core/src/transports/stdio.ts, exported as@sentry/mcp-core/transports/stdio. It now uses@sentry/coretracing, so mcp-core takes no Node SDK dependency.mcpis a real Stricli command (packages/cli/src/commands/mcp.ts) with its flags declared, so help is generated like every other command. Env merging and config validation live inpackages/cli/src/lib/mcp/{args,config}.ts, agent provider and telemetry setup inlib/mcp/server.ts. mcp-core stays free of CLI concepts. The command loadslib/mcp.ts, and that loads the server stack, only when it serves. The command module itself imports nothing from mcp-core (its help copies the skill names, and a test checks them againstALL_SKILLS), so docs generation andpnpm run clistill work without building mcp-core.~/.sentry/mcp.jsoncache,authsubcommands): deleted. CLI auth replaces it.@sentry/mcp-core/transports/stdio. The test client launchessentry mcpfrom CLI source. Smoke tests only target the hosted worker, so they needed no change.ensure-generated.mjsnow sends generator output to stderr, so a firstpnpm run cli mcpcannot write junk into the JSON-RPC stream.onUpstreamUnauthorizedwas dropped before. The refreshed token now reaches the context, and a regression test checks that later calls use it.npx @sentry/mcp-server@latest; the web install instructions are unchanged. User-facing docs mention the shared CLI login but do not steer installs tosentry mcp; themcp-qaskill drives the server from CLI source.docs/operations/stdio-auth.mdanddocs/releases/stdio.mdare rewritten package-first, andstdio-auth.mddocuments that each server process uses one account.Parity
@sentry/mcp-server@sentry/mcp-server(andsentry mcp)--access-token/SENTRY_ACCESS_TOKENSENTRY_AUTH_TOKEN=<token>andSENTRY_FORCE_ENV_TOKEN=1were set, through the same env-token path, so it wins over a stored login. It also replaces an existingSENTRY_AUTH_TOKEN/SENTRY_TOKEN, since the flag is the explicit choice. The flag wins over the env var. The token is sent to the--host/--urltarget as before; an org token (sntrys_) issued for another host is refused withHostScopeError. Prints one deprecation warning on stderr, without the token; the flag value is redacted from telemetry. Docs, help, andserver.jsonnow lead withSENTRY_AUTH_TOKEN(+SENTRY_FORCE_ENV_TOKEN=1, andSENTRY_HOST/SENTRY_URLfor self-hosted).~/.sentry/mcp.jsoncachesentry auth login, orSENTRY_AUTH_TOKEN/SENTRY_TOKEN), refreshed after an upstream 401. In a TTY it starts the CLI login. Over pipes it fails with an error naming the login command:npx -y @sentry/mcp-server auth loginfrom the package,sentry auth loginfromsentry mcp. The old cache is not read.--host/SENTRY_HOST,--url/SENTRY_URL--host/--url. One difference: anhttp://SENTRY_URLnow maps to--hostplus--insecure-http(the CLI's self-hosted behavior) instead of being rejected.--insecure-http--urland for sentry.io hosts.--mcp-url/MCP_URL,--sentry-dsn/SENTRY_DSN/DEFAULT_SENTRY_DSN--skills/MCP_SKILLS,--all-skills,--disable-skills/MCP_DISABLE_SKILLSseerfrom the defaults on self-hosted hosts--agent-provider/EMBEDDED_AGENT_PROVIDER,--openai-base-url,--openai-model/OPENAI_MODEL,--anthropic-base-url,--anthropic-model/ANTHROPIC_MODEL, provider API keys--organization-slug,--project-slug,--experimental--help/-h,--version/-vsentry-mcp --helplistsmcp,auth, andhelp;sentry-mcp mcp --helplists the flags and env vars. A lone-vstill prints the version; anywhere else-vis the CLI's--verbose. Changed: the output is the bare version (0.48.0), like the CLI, instead ofsentry-mcp 0.48.0.--flag=(for example--sentry-dsn=to turn off telemetry), values with a line break--flag valuefirst (splitInlineFlagValues).SENTRY_CLIENT_ID,SENTRY_MCP_AUTH_CACHEsentry-mcp auth login|logout|statusauthcommands:login(with all its flags, including--url),logout,status,list,switch,refresh,token,whoami. They use the CLI session. Account pickers take the account as an argument, since the Ink picker is not bundled.Dependency direction guard
sentry→@sentry/mcp-core→@sentry/toolkit-core, and@sentry/mcp-cloudflare→@sentry/mcp-core. No edge runs the other way.pnpm run lintenforces this with two checks:no-restricted-importsoverride banssentry,sentry/**, and relative CLI paths insidepackages/mcp-coreandpackages/toolkit-core.scripts/check-workspace-deps.mjs(lint:deps) reads every workspacepackage.json. It fails on any cycle, on mcp-core reachingsentryor mcp-cloudflare, and on toolkit-core reachingsentryor mcp-core.The rule is documented in
AGENTS.mdanddocs/architecture/overview.md#package-dependency-direction. Capabilities that only the CLI host has (SQLite cache, DSN detection from local files, file uploads) are injected into mcp-core through interfaces defined in mcp-core or toolkit-core.sentry mcpalready works this way for the access token and refresh callback inServerContext.Release and MCP registry
Every CLI release now publishes
@sentry/mcp-serverat the CLI's version, so the next one goes from 0.42.0 to the CLI's next version (0.48.0). The privatemcp-*packages keep their own versions.packages/cli/script/bump-version.tssetspackages/mcp-server/package.jsonto the CLI version on--preand to the next-devversion on--post. The bundle script fails if the two versions differ.cli-build.ymlbundles, tests, and packs the package and uploads it asmcp-server-npm-package. Thepackages/cliCraft workspace publishes it through a second npm target and attaches it to thecli@<version>GitHub release.packages/mcp-serverCraft workspace, the Release workflow'smcpoption, and the packing steps inmerge-jobs.ymlare removed.mcp-registry.ymlnow runs on stablecli@releases and strips the prefix. A manual run with-f version=Xusescli@X, or the bare tags used up to 0.42.0.mcpName: io.github.getsentry/sentry-mcpis unchanged;server.json's environment variables now declareSENTRY_AUTH_TOKEN(required, secret) andSENTRY_FORCE_ENV_TOKEN(default1) instead ofSENTRY_ACCESS_TOKEN.@sentry/mcp-serverbundle@sentry/mcp-serverstays the recommended, supported package. It ships one dependency-free file built from the CLI's own runner, so the package andsentry mcprun the same code, including self-hosted Sentry.packages/cli/src/mcp-server.tsrunscli.ts'sstartCli()withmcp-server-app.ts, a route map of the CLI'smcp(the default command),auth, andhelp. The runner takes aCliEntrythat loads the application, sosentry(sentry-cli.ts) andsentry-mcpdiffer only in their route map.lib/application.tsholds the Stricli application setup that used to sit inapp.ts.packages/mcp-server/script/bundle.tsbundles the entry intopackages/mcp-server/dist/sentry-mcp.cjs.mcp:isMcpInvocation()findsmcpafter leading global flags, or no command at all wheremcpis the default. The runner then runs Stricli without the CLI's telemetry, recovery middleware, and update check (the server owns stdout and has its own telemetry). The command resolves when the client closes stdin, and only then does the runner close the dispatcher and arm the force-exit backstop.lib/app-identity.tsreplaceslogin-command.tsandusage.ts. Each entry registers its name, and hints (AuthError, refresh and device-flow failures, host-scope errors) and help examples use it:sentry auth login,sentry-mcp auth login, ornpx -y @sentry/mcp-server auth loginwhen npx launched the process (npm_command=execor an_npxpath). MCP telemetry keepsapp.server.distributionatsentry mcpor@sentry/mcp-server.--help,--version, andauth …do not load mcp-core's server, the provider factory, the MCP telemetry, or the stdio transport;commands/mcp.tsimportslib/mcp.tsonly when it serves, andlib/mcp.tsimportslib/mcp/server.tsonly after setup checks pass. A bare--version(or lone-v) returns before the application loads.--helpandauthstill load@sentry/node, because the CLI's command builder and error reporting import it, same assentry --help.261e371f, separate commit): stdio uses@modelcontextprotocol/serverand its stdio transport, like the Cloudflare worker.startStdio()returns aclosedpromise; v2's transport closes when stdin ends, which is what lets the command return.c0243b5athen removes SDK v1 from mcp-core:buildServer()always builds a v2McpServer, thesdkVersionoption is gone, and@modelcontextprotocol/sdkis only a dev dependency of mcp-core (its tests use the in-memory client). The Cloudflare worker keeps its own SDK dependency forStreamableHTTPClientTransport. Bothsentry mcpand the bundle serve 14 tools over v2 and exit 0 within ~13–16 ms of stdin closing.__SENTRY_CLI_SYNTAX_HIGHLIGHT__=false(perf(cli): Load syntax highlighting lazily and allow compiling it out #1765) and a new__SENTRY_CLI_INK_UI__=false(lib/select-prompt.ts) compile out highlight.js/parse5 and Ink;zod/v3resolves to a shared stub (packages/cli/script/lib/zod-v3-stub-plugin.ts) in both this bundle and the CLI's (script/bundle.ts,script/build.ts):@ai-sdk/provider-utilsand@mastra/schema-compatonly reach it for Zod 3 inputs, and nothing we bundle builds Zod 3 schemas. The stub keepsZodTypea class so Mastra'sinstanceofcheck is false, and throws a clear error if a Zod 3 path ever runs. A test bundles the real Mastra client and provider-utils, runs a workflow create/start, and converts Zod 4 and JSON schemas. With SDK v1 gone from mcp-core, the bundle no longer needs a v1 stub and fails if any@modelcontextprotocol/sdkmodule reaches it.sentry init, and build/sourcemap/debug-file code. The SQLite WASM fallback is also left out, so the engine moves from>=22.13to>=22.15(nativenode:sqlite), and the bin exits early with a clear error on older Node.js.@modelcontextprotocol/sdkmodule) contributes code to the output, or if the file grows past 3.75 MiB (MAX_BUNDLE_BYTES, ~240 KB over the measured size; left as is, since removing SDK v1 saved only ~1 KB here, where it was already stubbed).packages/mcp-server/test/bundle.test.mjsruns the built file:initializeplustools/listover stdio with--sentry-dsn=(withSENTRY_AUTH_TOKEN, and with the deprecated--access-token, checking the warning is on stderr once and never echoes the token), exit on stdin close, no runtime dependencies, bare--versionand-v,--helplisting exactlymcp/auth/help,mcp --helpexamples namingsentry-mcp, the login hint with and without npx,auth status, and rejecting other CLI commands.cli-build.ymlbundles, tests, and packs the package next to the CLI's npm package.The old
@sentry/mcp-server/transports/stdioexport is gone (now@sentry/mcp-core/transports/stdio), and the standalone clean-consumer workflow (mcp-server-package.yml) is removed; the bundle test replaces it.Release note: do not run
npm deprecate. Users on Node.js 22.13 or 22.14 need to upgrade Node.js.Measurements (Node 22, this sandbox; startup rows are the median of 7 runs, idle RSS is 5 runs)
53fc92fe)9977bb0ca98cb249)sentry-mcp --versionsentry-mcp --helpsentry-mcp auth status(logged out)initialize+tools/list--help,auth status, and idle RSS were measured at7a2f0a2a; the two later commits only add the-vfast path and move a string list, and the bundle grew 89 bytes.CLI
dist/index.cjs: 7,426,174 B beforec0243b5a→ 7,203,971 B without SDK v1 (−222 KB; ajv and most of zod-to-json-schema go with it) → 7,142,739 B with thezod/v3stub (−61 KB) → 7,143,333 B ata98cb249.The bundle ends up about the same size as before even with
550 KB of savings (Zod locales −264 KB, SDK v1 and Zod 3 −280 KB), because it now carries the CLI runner, the fullauthcommands, and generated help. Largest inputs:@sentry/api482 KB,@modelcontextprotocol/server291 KB (156 KB of it ajv),@sentry/server-utils242 KB,zod193 KB, mcp-core's OTel semantics 187 KB,@sentry/core162 KB.mcp-core CJS output
Nothing builds or consumes mcp-core CJS anymore. #1732, now merged into this branch from main, switched
packages/mcp-core/tsdown.config.tstoformat: ["esm"]. mcp-core is"type": "module", and everyexportsentry maps onlytypesanddefault(.js) with norequirecondition. The CLI's esbuild bundle (CJS output) resolvesdefaultand converts the ESM itself, andscripts/check-build-imports.tsnow checksdist/server.js. This PR does not touch the build format.Verification
pnpm run tsc,pnpm run lint(includeslint:deps), and CLIci:policypass.pnpm run test: toolkit-core, mcp-core, mcp-cloudflare, mcp-test-client, docs-mcp, local, and cli-docs pass. CLI: 12,807 pass; the 6 failures are chmod-based tests (completionsEACCES/EPERM, read-only DB repair, upgrade lock permissions, unreadable DSN file, file-changes I/O) that fail in this sandbox's filesystem and do not touch this diff. The MCP, auth, app-identity, startup, help, and completion suites pass.pnpm --filter sentry run generate:docspasses withpackages/mcp-core/distremoved, which is thesentry-cli-docsCI condition.test/lib/mcp/args.test.tsparses with the command's real Stricli parameters (test/lib/mcp/parse-flags.ts);mcp-start.test.tsandmcp-auth.test.tsdriveserveMcp()andwithConfiguredTarget()through it;mcp-command.test.tscoversisMcpInvocation, the{mcp, auth, help}app, no CLI telemetry formcp, teardown only after the server returns, setup failures,--help, the help's skill list againstALL_SKILLS, and unknown flags;app-identity.test.tscovers names and npx hints.usage*.test.ts,mcp/auth.test.ts, andmcp-run.test.tsare deleted with their modules.pnpm --filter @sentry/mcp-server run bundle(withSENTRY_AUTH_TOKENunset) builds 3,689,429 B ata98cb249;test:bundlepasses 13/13.node dist/bin.cjs mcpanswerstools/listwith 14 tools over SDK v2 and exits 0 when stdin closes. With--access-token, stdout carries only JSON-RPC frames and stderr has the one deprecation line, without the token. CLItest/e2e/bundle.test.ts+library.test.tspass 26/26.a98cb249:pnpm run lintpasses;tscpasses for cli, mcp-core, mcp-cloudflare, mcp-server-evals, and mcp-test-client; mcp-core (1,890), mcp-cloudflare (443), and mcp-test-client (82) tests pass. CLItest/lib test/commands test/types test/script: 12,816 pass, 11 fail, and all 11 fail the same way without this change (6 chmod-based tests, plus 5 login-hint wording tests inerrors,oauth, andauto-login-host-guardthat seenpx -y sentrybecause the sandbox runs vitest through npx).--access-tokentests (mcp-start.test.ts): it serves the same token and refresh result asSENTRY_AUTH_TOKEN+SENTRY_FORCE_ENV_TOKEN=1, overrides a stored login before and after startup, overridesSENTRY_AUTH_TOKEN/SENTRY_TOKEN, leavesprocess.envuntouched, prints the hint once to stderr and nothing to stdout, and keeps the token out of the hint and ofMalformedAuthTokenError/HostScopeError. The existing self-hosted, org-token, and.sentryclirccases still pass.craft config --workspace packages/cliand the release checks above are unchanged from the earlier verification.Noticed, not changed:
serverInfo.versionininitializereports mcp-core's package version (0.42.0), as it did before this PR, not the CLI/package version.via @BYK.
--
View Session in Sentry